#include "StdAfx.h"
#include "ButtonStrategy.h"
//#include "HiddenWindow.h"	// for Some Strategies we need to create
							// a hidden window and draw the buttons on it							

////
// We are delay-loading the UXTheme.dll. In case we are running on 
// a system where the dll doesn't exist, we'll only load it we know
// that this is a system where it should exist
//// 
#include "uxtheme.h"
////
// We are delay-loading the DWMapi.dll. In case we are running on 
// a system where the dll doesn't exist, we'll only load it we know
// that this is a system where it should exist
//// 
#include "dwmapi.h"

using namespace Ooganizer;

//******************************************************************** 
// Clss         ButtonStrategy	
//
// Programmer	Daniel Romischer
//              Ooganizer Development Team
//
// Description	Base/Abstract Class for all Button Strategies
//
// Note			CalcCaptionRect() and CalcCaptionButtonRect()
//				is implemented in the base class for now (as it appears
//				to be the same calculation for all Button Strategies).
//
// Created	    06-01-2008
//********************************************************************
//////////////////////////////////////////////////////////////////////
//******************************************************************** 
// Construction / Destruction
//******************************************************************** 
//////////////////////////////////////////////////////////////////////
ButtonStrategy::ButtonStrategy(void)
{
}
ButtonStrategy::~ButtonStrategy(void)
{
}
//////////////////////////////////////////////////////////////////////
// Func: CalcCaptionRect()
// Desc: Calculates the dimensions of the Caption Bar
//		 
// Prms: +hWnd, handle to a Windows
//		 +-Rect, returns the x,y RECT area dimension coordinates of the caption bar
//		 +-SIZE, returns the width and height of the Caption bar
//////////////////////////////////////////////////////////////////////
void ButtonStrategy::CalcCaptionRect(HWND hWnd, RECT &RectCaption, SIZE &heightNwidth)const
{		
	RECT Rect;
	SIZE sFrame;
	DWORD dStyle = GetWindowLong( hWnd, GWL_STYLE );	

	// Get frame size of window 
	// (x and y height width dim of the resizable or non-resizable windows frame)	
	sFrame.cy = GetSystemMetrics( ( dStyle & WS_THICKFRAME ) ? SM_CYSIZEFRAME : SM_CYFIXEDFRAME );	
	sFrame.cx = GetSystemMetrics( ( dStyle & WS_THICKFRAME ) ? SM_CXSIZEFRAME : SM_CXFIXEDFRAME );	

	// Gets the location of the Window
	GetWindowRect( hWnd, &Rect );	

	// Height and Width of the Window
	LONG height = Rect.bottom - Rect.top;	// Window height not intersting to us (not used)
	LONG width  = Rect.right - Rect.left;		

	// Pass the CaptionBar Dimension out
	RectCaption.top = sFrame.cy; // 4, 8
	RectCaption.left = sFrame.cx; // 4, 8
	RectCaption.right = width - sFrame.cy; // 771

	// SM_CYCAPTION = The height of a caption area, in pixels
	// SM_CYBORDER = The height of a window border
	int heightCaption = GetSystemMetrics( SM_CYCAPTION );  // 20
	int heightWindowBorder = GetSystemMetrics( SM_CYBORDER ); // 1
	
	RectCaption.bottom = heightCaption;

	//heightCaption gives us the correct caption height, but in order to get the exact RECT location,
	//calculated from top left, we need to add sFrame.cy to it. ~we substract the bottom border because,
	//otherwise the height will be too long							

	//sFrame.cy + heightCaption - heightWindowBorder;

	// sample return
	// top = 4, left = 4, bottom = 23, right = 771

	// Pass out the height & Width of the CaptionBar
	heightNwidth.cx = heightCaption;
	heightNwidth.cy = width;
}
//******************************************************************** 
// Clss         ClassicButtonStrategy	
//
// Description	Implementation for our Windows Classic Theme Strategy
//
// Note			Uses DrawFrameControl() to draw the Button. This will
//				Only work in Windows2000/XP without theme (classic View)
//
// Created	    06-01-2008
//********************************************************************
//////////////////////////////////////////////////////////////////////
//******************************************************************** 
// Construction / Destruction
//******************************************************************** 
//////////////////////////////////////////////////////////////////////
ClassicButtonStrategy::ClassicButtonStrategy()
{	
}
ClassicButtonStrategy::~ClassicButtonStrategy()
{
}
//////////////////////////////////////////////////////////////////////
// Func: draw()
// Desc: generic draw function - called for all default messages
//////////////////////////////////////////////////////////////////////
void ClassicButtonStrategy::draw(HWND hWnd, const HDC &hDc, const RECT &rPos) const
{
	// Use the regular Frame Control *Windows Classic*	
	// DrawFrameControl( hDc, const_cast<LPRECT>(&rPos), DFC_BUTTON, DFCS_BUTTONPUSH );		
	
	HICON hIcon = (HICON) LoadImage(NULL, L"C:\\bridge.ico", IMAGE_ICON, 0, 0, LR_LOADFROMFILE); 
	DrawIcon(hDc, rPos.left, rPos.top, hIcon);
}
//////////////////////////////////////////////////////////////////////
// Func: drawButtonUp()
// Desc: draw the button in an up state
//////////////////////////////////////////////////////////////////////
void ClassicButtonStrategy::drawButtonUp(HWND hWnd, const HDC &hDc, const RECT &rPos) const
{
	// Use the regular Frame Control *Windows Classic*	
	// DrawFrameControl( hDc, const_cast<LPRECT>(&rPos), DFC_BUTTON, DFCS_BUTTONPUSH );
	
	HICON hIcon = (HICON) LoadImage(NULL, L"C:\\bridge.ico", IMAGE_ICON, 0, 0, LR_LOADFROMFILE); 
	DrawIcon(hDc, rPos.left, rPos.top, hIcon);
}
//////////////////////////////////////////////////////////////////////
// Func: drawButtonDown()
// Desc: draw the button in a down state
//////////////////////////////////////////////////////////////////////
void ClassicButtonStrategy::drawButtonDown(HWND hWnd, const HDC &hDc, const RECT &rPos) const
{
	// Use the regular Frame Control *Windows Classic*	
	// DrawFrameControl( hDc, const_cast<LPRECT>(&rPos), DFC_BUTTON, DFCS_BUTTONPUSH | DFCS_PUSHED );	

	HICON hIcon = (HICON) LoadImage(NULL, L"C:\\bridge.ico", IMAGE_ICON, 0, 0, LR_LOADFROMFILE); 
	DrawIcon(hDc, rPos.left, rPos.top, hIcon);
}
//******************************************************************** 
// Clss         AeroButtonStrategy	
//
// Description	Implementation for our Windows Aero Theme Strategy
//
// Note			
//				
//
// Created	    06-01-2008
//********************************************************************
//////////////////////////////////////////////////////////////////////
//******************************************************************** 
// Construction / Destruction
//******************************************************************** 
//////////////////////////////////////////////////////////////////////
AeroButtonStrategy::AeroButtonStrategy()
{	
}
AeroButtonStrategy::~AeroButtonStrategy()
{
}
//////////////////////////////////////////////////////////////////////
// Func: CalcCaptionButtonRect()
// Desc: Calculates the dimensions of the Caption Button. Takes into
//		 account the number of caption buttons on the window and returns
//		 the pos (RECT) where to draw the Caption Button.
//		 
// Prms: +hWnd, handle to a Windows
//		 +-RectButtonPos, returns the x,y dimension of where to place the Button
//////////////////////////////////////////////////////////////////////
void AeroButtonStrategy::CalcCaptionButtonRect(HWND hWnd, RECT& RectButtonPos) const
{	
	// Button Constants
	const LONG BUTTON_MARGIN = 2;			// The Margin Space between the Buttons

	//The width of a button in a window caption or title bar, in pixels
	const LONG CAPTION_WIDTH = GetSystemMetrics(SM_CXSIZE);				// should be 28

	log(LOGGING_HIGH, "Caption Width = %i", CAPTION_WIDTH);

	RECT rect;
	SIZE size;
	// Get The dimensions of the CaptionBar
	CalcCaptionRect(hWnd,rect,size);

	// sample return from CalcCaptionRect()
	// top = 4, left = 4, bottom = 23, right = 771

	// On Aero the distance of the Button is 10 not 6. Calculating by multiplying top * 2 (=8)
	// ~this makes sense because our Rect start at the top most location (not where vista wants to draw the button
	const LONG TOP_PLACEMENT = (2 * rect.top) + BUTTON_MARGIN;
	const LONG BOTTOM_PLACEMENT = rect.bottom - BUTTON_MARGIN;

	// Left and Right Placement has to be calculated using the spacing on the right, the caption button widths,
	// of (close, max, min) and the margins in between the buttons. (RECT includes all caption buttons),
	// we also subtract rect.top from the left because a window border on right is not considered (+ another margin)
	const LONG RIGHT_PLACEMENT = rect.right - (CAPTION_WIDTH * 3) - (BUTTON_MARGIN * 3) - (rect.top + BUTTON_MARGIN);
	const LONG LEFT_PLACEMENT = RIGHT_PLACEMENT - CAPTION_WIDTH; // - BUTTON_MARGIN?

	////
	// Pass out the dimension of the CaptionButton
	////
	RectButtonPos.top = TOP_PLACEMENT;
	RectButtonPos.bottom = BOTTOM_PLACEMENT;	
	RectButtonPos.right = RIGHT_PLACEMENT;
	RectButtonPos.left = LEFT_PLACEMENT;
}
//////////////////////////////////////////////////////////////////////
// Func: draw()
// Desc: generic draw function - called for all default messages
//////////////////////////////////////////////////////////////////////
void AeroButtonStrategy::draw(HWND hWnd, const HDC &hDc, const RECT &rPos) const
{
	// HTHEME hTheme = OpenThemeData(hWnd, L"OkButton;Button;Window");
	// HTHEME hTheme = OpenThemeData(hWnd, L"Button");

	// DrawThemeParentBackground(hWnd,hDc,&rPos);
	// DrawThemeBackground(hTheme,hDc,0,0,&rPos,0);

	HICON hIcon = (HICON) LoadImage(NULL, L"C:\\VistaNoAero.ico", IMAGE_ICON, 0, 0, LR_LOADFROMFILE); 
	DrawIcon(hDc, rPos.left, rPos.top, hIcon);
}
//////////////////////////////////////////////////////////////////////
// Func: drawButtonUp()
// Desc: draw the button in an up state
//////////////////////////////////////////////////////////////////////
void AeroButtonStrategy::drawButtonUp(HWND hWnd, const HDC &hDc, const RECT &rPos) const
{	
	HICON hIcon = (HICON) LoadImage(NULL, L"C:\\bridge.ico", IMAGE_ICON, 0, 0, LR_LOADFROMFILE); 
	DrawIcon(hDc, rPos.left, rPos.top, hIcon);
}
//////////////////////////////////////////////////////////////////////
// Func: drawButtonDown()
// Desc: draw the button in a down state
//////////////////////////////////////////////////////////////////////
void AeroButtonStrategy::drawButtonDown(HWND hWnd, const HDC &hDc, const RECT &rPos) const
{
	HICON hIcon = (HICON) LoadImage(NULL, L"C:\\bridge.ico", IMAGE_ICON, 0, 0, LR_LOADFROMFILE); 
	DrawIcon(hDc, rPos.left, rPos.top, hIcon);
}
//******************************************************************** 
// Clss         VistaNoAeroStrategy	
//
// Description	Implementation for Vista when Aero (Glass) is not running
//
// Note			
//				
//
// Created	    06-01-2008
//********************************************************************
//////////////////////////////////////////////////////////////////////
//******************************************************************** 
// Construction / Destruction
//******************************************************************** 
//////////////////////////////////////////////////////////////////////
VistaNoAeroStrategy::VistaNoAeroStrategy()
{
}
VistaNoAeroStrategy::~VistaNoAeroStrategy()
{
}
//////////////////////////////////////////////////////////////////////
// Func: CalcCaptionButtonRect()
// Desc: Calculates the dimensions of the Caption Button. Takes into
//		 account the number of caption buttons on the window and returns
//		 the pos (RECT) where to draw the Caption Button.
//		 
// Prms: +hWnd, handle to a Windows
//		 +-RectButtonPos, returns the x,y dimension of where to place the Button
//////////////////////////////////////////////////////////////////////
void VistaNoAeroStrategy::CalcCaptionButtonRect(HWND hWnd, RECT& RectButtonPos) const
{	
	// Button Constants
	const LONG BUTTON_MARGIN = 2;			// The Margin Space between the Buttons

	//The width of a button in a window caption or title bar, in pixels
	const LONG CAPTION_WIDTH = GetSystemMetrics(SM_CXSIZE);			// 32 (appears to include left and righ Margin)	

	RECT rect;
	SIZE size;
	// Get The dimensions of the CaptionBar
	CalcCaptionRect(hWnd,rect,size);
	log(LOGGING_HIGH, "rect is top %i, bottom %i, left %i, right %i", rect.top, rect.bottom, rect.left, rect.right);

	// sample return from CalcCaptionRect()

	// Vista Aero
	// top = 4, left = 4, bottom = 23, right = 771

	// Vista NoAero
	// rect is top 8, bottom 27, left 8, right 831

	// On Aero the distance of the Button is 10 not 6. Calculating by multiplying top * 2 (=8)
	// ~this makes sense because our Rect start at the top most location (not where vista wants to draw the button
	const LONG TOP_PLACEMENT = 10; //(2 * rect.top) + BUTTON_MARGIN;
	const LONG BOTTOM_PLACEMENT = rect.bottom - BUTTON_MARGIN;

	// Left and Right Placement has to be calculated using the spacing on the right, the caption button widths,
	// of (close, max, min) and the margins in between the buttons. (RECT includes all caption buttons),
	// we also subtract rect.top from the left because a window border on right is not considered (+ another margin)
	// 96 	
	const LONG RIGHT_PLACEMENT = rect.right - 96;
	const LONG LEFT_PLACEMENT = RIGHT_PLACEMENT - 28; // - BUTTON_MARGIN?

	////
	// Pass out the dimension of the CaptionButton
	////
	RectButtonPos.top = TOP_PLACEMENT;
	RectButtonPos.bottom = BOTTOM_PLACEMENT;	
	RectButtonPos.right = RIGHT_PLACEMENT;
	RectButtonPos.left = LEFT_PLACEMENT;
}
//////////////////////////////////////////////////////////////////////
// Func: draw()
// Desc: generic draw function - called for all default messages
//////////////////////////////////////////////////////////////////////
void VistaNoAeroStrategy::draw(HWND hWnd, const HDC &hDc, const RECT &rPos) const
{
	HICON hIcon = (HICON) LoadImage(NULL, L"C:\\VistaNoAero.ico", IMAGE_ICON, 28, 15, LR_LOADFROMFILE); 
	DrawIcon(hDc, rPos.left, rPos.top, hIcon);
}
//////////////////////////////////////////////////////////////////////
// Func: drawButtonUp()
// Desc: draw the button in an up state
//////////////////////////////////////////////////////////////////////
void VistaNoAeroStrategy::drawButtonUp(HWND hWnd, const HDC &hDc, const RECT &rPos) const
{	
}
//////////////////////////////////////////////////////////////////////
// Func: drawButtonDown()
// Desc: draw the button in a down state
//////////////////////////////////////////////////////////////////////
void VistaNoAeroStrategy::drawButtonDown(HWND hWnd, const HDC &hDc, const RECT &rPos) const
{
}
//******************************************************************** 
// Clss         XPButtonStrategy	
//
// Description	Implementation for Windows XP Themed Strategy
//
// Note			
//				
//
// Created	    06-01-2008
//********************************************************************
//////////////////////////////////////////////////////////////////////
//******************************************************************** 
// Construction / Destruction
//******************************************************************** 
//////////////////////////////////////////////////////////////////////
XPButtonStrategy::XPButtonStrategy()
{	
}
XPButtonStrategy::~XPButtonStrategy()
{
}
//////////////////////////////////////////////////////////////////////
// Func: draw()
// Desc: generic draw function - called for all default messages
//////////////////////////////////////////////////////////////////////
void XPButtonStrategy::draw(HWND hWnd, const HDC &hDc, const RECT &rPos) const
{
}
//////////////////////////////////////////////////////////////////////
// Func: drawButtonUp()
// Desc: draw the button in an up state
//////////////////////////////////////////////////////////////////////
void XPButtonStrategy::drawButtonUp(HWND hWnd, const HDC &hDc, const RECT &rPos) const
{	
}
//////////////////////////////////////////////////////////////////////
// Func: drawButtonDown()
// Desc: draw the button in a down state
//////////////////////////////////////////////////////////////////////
void XPButtonStrategy::drawButtonDown(HWND hWnd, const HDC &hDc, const RECT &rPos) const
{
}